﻿using System.Text;

namespace TPXSDK.NET.Mission.Instruction;

internal class InstRepeat : Tokenizer
{
    private const int ForeverCnt = 9999;
    public InstRepeat(TokenizerAdmin admin)
    {
        Admin = admin;
        KeyName = "repeat";
        KeyValue = (int)FlyCmdId.CMD_REPEAT;
        Usage = "repeat –line";
        Description = @"This command can be used to repeat all or portions of a flight program. If line is not specified, this command resets the command buffer to the first command.";
    }

    public override bool Process()
    {
        var flyCmp = Admin?.Compiler; if (null == flyCmp) return false;
        var tokens = flyCmp.GetLineTokens();
        if (null == tokens)
        {
            flyCmp.ErrorMsg = $"{KeyName} Invalid Usage";
            return false;
        }
        /*
         * If line is not specified, this command resets
         * the command buffer to the very first command.
         * If your Autopilot is executing a defined pattern,
         * the first command is the first command in the pattern.
         * Otherwise the first command is the thread's first command.
         */

        var cmd = new FlyCmdItem
        {
            Id = (byte)KeyValue,
            LineNum = tokens[0].Row
        };

        tokens.RemoveAt(0);// Remove cmd Name

        cmd.P1 = (byte)ParaType.NUMBER;
        cmd.P2 = 0;
        if (tokens.Count == 1)
        {
            if (tokens[0].Type == TokenType.NUMBER)
            {
                try
                {
                    cmd.P2 = FlyUtils.ToInt16(tokens[0].Name);
                }
                catch (Exception)
                {
                    flyCmp.ErrorMsg = $"{KeyName} Invalid param";
                    return false;
                }
            }
            else if (tokens[0].Name.Equals("forever", StringComparison.CurrentCultureIgnoreCase))
            {
                cmd.P2 = ForeverCnt;
            }
            else
            {
                flyCmp.ErrorMsg = $"{KeyName} Invalid param";
                return false;
            }
        }

        // 参数作用域有效性判定
        var rang = Math.Abs(cmd.P2);
        if (0 != cmd.P2)
        {
            if (rang > flyCmp.CmdList.Count && ForeverCnt != cmd.P2)
            {
                flyCmp.ErrorMsg = $"{KeyName} parameter out range, should <{flyCmp.CmdList.Count}.";
                return false;
            }
        }

        flyCmp.CmdList.Add(cmd);
        return true;
    }

    public override void Reverse(FlyCmdItem cmd, StringBuilder sb)
    {
        if (ForeverCnt == cmd.P2)
            sb.AppendLine($"{KeyName} forever");
        else
            sb.AppendLine(cmd.P2 != 0 ? $"{KeyName} {cmd.P2}" : KeyName);
    }
}
